AWSアクセスキーをGitリポジトリに混入させないために git-secrets を導入した
先日開催されたAWS Summit Tokyo 2017、わたしもいくつかセッションを聴講してきたのですが、「DevSecOps on AWS - Policy in Code」というセッション1にてgit-secrets
というツールが紹介されていました。
これ以外にも、いくつかのセッションで言及されていたと思います。
git-secrets
のことは以前から聞いてはいたのですが、自分自身があまりコードを書く環境にいなかったので、良くないとは思いつつも今まであまり気にしていませんでした。
ただ、AWSアクセスキーの漏洩が原因と思われる話を聞く機会はなかなか減りませんし、考えてみれば自分でも、AWSクレデンシャル情報に触れる機会の多いこの頃。
ちょうど良い機会と思って、自分の環境にも導入しました。
インストール
macOSにHomebrew環境の場合は、下記を実行するだけでインストールは完了です。
$ brew update $ brew install git-secrets
それ以外の環境への導入は、上述したURLにあるとおりmake install
すれば良いでしょう。
というかgit-secrets
の実体はBASHスクリプトなので、PATHの通ったところに実行権限付きで置くだけでも動作します(MANPAGEも必要なら別途必要)。
今回自分は試しにそうやってみました。
普段からホームディレクトリ直下のbin/
ディレクトリにはPATHを通してあるので、そこへインストールします。
$ curl -O https://raw.githubusercontent.com/awslabs/git-secrets/master/git-secrets $ chmod +x ./git-secrets $ mv -i ./git-secrets ~/bin/ $ which git-secrets /Users/watanabe/bin/git-secrets
git secrets
と実行してみて、ヘルプメッセージが表示されればインストール完了です。
$ git secrets usage: git secrets --scan [-r|--recursive] [--cached] [--no-index] [--untracked] [<files>...] :
設定(1)
git-secrets
を置くだけでは使えません。AWSアクセスキーの標準パターンをGitの設定ファイルに書き込む必要があります。
$ git secrets --register-aws --global
下記の様に、~/.gitconfig
に設定が追記されたら成功です。
diff --git a/.gitconfig b/.gitconfig index 027f0df..4f37ac5 100644 --- a/.gitconfig +++ b/.gitconfig @@ -13,3 +13,10 @@ trustExitCode = true [commit] template = /Users/watanabe/.stCommitMsg +[secrets] + providers = git secrets --aws-provider + patterns = [A-Z0-9]{20} + patterns = (\"|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)(\"|')?\\s*(:|=>|=)\\s*(\"|')?[A-Za-z0-9/\\+=]{40}(\"|')? + patterns = (\"|')?(AWS|aws|Aws)?_?(ACCOUNT|account|Account)_?(ID|id|Id)?(\"|')?\\s*(:|=>|=)\\s*(\"|')?[0-9]{4}\\-?[0-9]{4}\\-?[0-9]{4}(\"|')? + allowed = AKIAIOSFODNN7EXAMPLE + allowed = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
ちなみにallowed
の行にあるのは、AWS自身が公式ドキュメントで使用しているアクセスキーのサンプルですね。2
これらに対しては警告を出さないよう、例外指定ができる機能があります。
やってみる(1)
試しにやってみます。
上記のサンプルからちょっとだけ変更したキー情報を含む、試験用のクレデンシャルファイルを作成しました。
- AKIAIOSFODNN7EXAMPLo
- wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEo
これらが検知できればスキャンは成功です。
Gitリポジトリじゃないファイルやディレクトリをスキャンするには--no-index
オプションを使用すると良いみたいです。
$ ls -l total 8 -rw-r--r-- 1 watanabe staff 116 6 11 21:41 aws_credentials.txt $ cat aws_credentials.txt [default] aws_access_key_id = AKIAIOSFODNN7EXAMPLo aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEo $ git secrets --scan --no-index fatal: Not a git repository (or any of the parent directories): .git aws_credentials.txt:2:aws_access_key_id = AKIAIOSFODNN7EXAMPLo aws_credentials.txt:3:aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEo [ERROR] Matched one or more prohibited patterns Possible mitigations: - Mark false positives as allowed using: git config --add secrets.allowed ... - Mark false positives as allowed by adding regular expressions to .gitallowed at repository's root directory - List your configured patterns: git config --get-all secrets.patterns - List your configured allowed patterns: git config --get-all secrets.allowed - List your configured allowed patterns in .gitallowed at repository's root directory - Use --no-verify if this is a one-time false positive
「Gitリポジトリじゃない」と言いながらも、ちゃんとスキャンしてくれました。なんというツンデレ
やってみる(2)
対象がGitリポジトリであればオプションは要らないし、fatalなんて言われません。
$ git init $ git add . $ git commit -m 'first' $ git secrets --scan aws_credentials.txt:2:aws_access_key_id = AKIAIOSFODNN7EXAMPLo aws_credentials.txt:3:aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEo [ERROR] Matched one or more prohibited patterns :
この場合はgit ls-files
でリストアップされるファイルだけが対象になります。
.gitignore
に書いてあるような、リポジトリに含まれないファイルはスキャンしないので、毎回false positiveが発生するようなこともないでしょうね。
設定(2) & やってみる(3)
とはいえこのままだと、毎回手動でスキャンする必要があります。
git-secrets
にはコミット時にhookする機能もあるので、こちらを有効にしてみます。
$ git secrets --install ✓ Installed commit-msg hook to .git/hooks/commit-msg ✓ Installed pre-commit hook to .git/hooks/pre-commit ✓ Installed prepare-commit-msg hook to .git/hooks/prepare-commit-msg
先ほど作成したサンプルのクレデンシャルファイルをコピーして、レポジトリに追加してみます。
$ cp -p aws_credentials.txt aws_credentials2.txt $ git add ./aws_credentials2.txt $ git commit -m 'hook test' aws_credentials2.txt:2:aws_access_key_id = AKIAIOSFODNN7EXAMPLo aws_credentials2.txt:3:aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEo [ERROR] Matched one or more prohibited patterns : $ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: aws_credentials2.txt
見事にコミットが食い止められました。
公開を前提とするようなリポジトリには、忘れず有効にしておきたいですね。
設定(3)
リポジトリごとの設定も試してみます。
例えば先ほどallowed
の話をしましたが、このレポジトリに限っては「AKIAIOSFODNN7EXAMPLo」も例外扱いにしてみます。
$ git secrets --scan aws_credentials.txt:2:aws_access_key_id = AKIAIOSFODNN7EXAMPLo aws_credentials.txt:3:aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEo : $ git secrets --add --allowed AKIAIOSFODNN7EXAMPLo $ git secrets --scan aws_credentials.txt:3:aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEo :
2行目は警告されなくなりました。
この設定はリポジトリローカルの設定ファイル(.git/config
)に書き込まれているので、他のレポジトリには影響しません3。
こんな感じで、全体的にgit-secrets
を使えるようにしつつ、リポジトリごとにカスタマイズしていくことが出来るようになっています。
Sourcetreeでも使ってみる
ふと思い立って、GUIのGitクライアントであるSourcetreeで上記のリポジトリを扱ってみました。
その結果がこちらになります:
git-secrets
が正しく読み込まれず、hookに設定したスクリプトがエラーを吐いてしまいました。
これはよろしくありません。ツンデレさんは扱いが面倒です
解決方法はいくつかあるのではないかと思うのですが、自分で試してみた限り、
- GitはSourcetreeビルトインのものではなく、システム(macOS)のものを使うよう設定する
- 指定した
git
と同じパスにgit-secrets
を置く
という条件が必要でした。
手軽に解決するためには、下記の手順がよいかと思います。
git
とgit-secrets
をHomebrewで導入する($ brew install git git-secrets
)- Sourcetreeの設定で
/usr/local/bin/git
を指定する(環境設定 > Git > 「システムの Git を使用する」)
特に 2. は、/usr/bin/git
や/usr/local/Cellar/git/2.13.1/bin/git
4等にならないよう注意が必要です。
こうしておけば、commit時にちゃんとgit-secrets
が働いてくれました。ちょろい
所感
使う前は「Set it and Forget it (一度設定したら後は放っておけばよい)」的なものかと思っていたんですが、残念ながらそうではなさそうでした。
とはいえ「リポジトリ単位」に限って言えば、最初に設定してしまえばずっと有効ですし、リポジトリごとにカスタマイズできたりhookを手軽に導入できたりと、その使い勝手の良さと有効性は大きいように思えます。
転ばぬ先の杖として、これまで使ったことのない方も導入を検討してみては如何でしょうか。
蛇足
なおHomebrewにはgit-secret
(末尾に「s」なし)というものもあって、最初間違えてインストールしそうになってしまったのは秘密です。。。
$ brew info git-secret git-secret: stable 0.2.2 (bottled), HEAD Bash-tool to store the private data inside a git repo. https://sobolevn.github.io/git-secret/
でもこれはこれで面白そうなツールなので、いつか折を見て使ってみたいと思います。